/*
 * File:     mainwindow.cpp
 * Authors: Dominic Stalder, Thomas Bruederli
 *
 * Implements the main application window which defines the menus
 * and connects the driver signals with the central widget slots.
 *
 * This file is part of the Qt-based cross-platform Wii device driver.
 *
 * Copyright (C) 2009-2010, Dominic Stalder & Thomas Bruederli
 * Licensed under the GNU Lesser General Public License (LGPL) as published
 * by the Free Software Foundation at http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * $Id: mainwindow.cpp 5 2010-03-03 09:10:12Z roundcube $
 */

#include <QtGui>
#include <iostream>
#include "mainwindow.h"
#include "boardwidget.h"
#include "controllerwidget.h"

/** 
 * Class constructor.
 * 
 * Creates the main application window with the menus and connects the driver with the central widget slots.
 *
 * @see MainWindow
 */
MainWindow::MainWindow()
{
	setWindowTitle(tr("Wii Device Driver"));

	createActions();
	createMenus();
	createStatusBar();

	boardUI = new BoardWidget(this);
	controllerUI = new ControllerWidget(this);
	
	QWidget *mainWidget = new QWidget(this);
	QHBoxLayout *mainLayout = new QHBoxLayout;
	mainLayout->addWidget(boardUI);
	mainLayout->addWidget(controllerUI);
	mainWidget->setLayout(mainLayout);
	
	setCentralWidget(mainWidget);
	
	wiiboard = new WiiDeviceDriver(WiiDeviceDriver::TYPE_BALANCEBOARD);
	wiicontroller = new WiiDeviceDriver(WiiDeviceDriver::TYPE_CONTROLLER);
	
	// connect wiibaord driver signals with UI slots
	connect(wiiboard, SIGNAL(logMessageGenerated(const QString&, int, int)), this, SLOT(setStatus(const QString&, int, int)));
	connect(wiiboard, SIGNAL(instructionChanged(int, const QString&, bool)), boardUI, SLOT(setInstructions(int, const QString&, bool)));
	connect(wiiboard, SIGNAL(kilogramsChanged(float, float, float, float, float)), boardUI, SLOT(setValues(float, float, float, float, float)));
	connect(wiiboard, SIGNAL(buttonChanged(int, int)), boardUI, SLOT(buttonChanged(int, int)));

	connect(wiicontroller, SIGNAL(instructionChanged(int, const QString&, bool)), controllerUI, SLOT(setInstructions(int, const QString&, bool)));
	connect(wiicontroller, SIGNAL(buttonChanged(int, int)), controllerUI, SLOT(buttonChanged(int, int)));
	connect(wiicontroller, SIGNAL(orientationChanged(double, double, double)), controllerUI, SLOT(orientationChanged(double, double, double)));
	connect(wiicontroller, SIGNAL(logMessageGenerated(const QString&, int, int)), this, SLOT(setStatus(const QString&, int, int)));
	
	connector = new WiiDeviceConnector(wiiboard, wiicontroller);
	//connector->start();
}

/**
 * Stops the driver thread.
 *
 * @param  *event  Qt event sent by Qt framework
 */
void MainWindow::closeEvent(QCloseEvent *event)
{
	if (connector->isRunning())
	{
		connector->stop();
		connector->wait();
	}
	
	if (wiiboard->isRunning())
	{
		wiiboard->stop();
		wiiboard->wait();
	}
	
	if (wiicontroller->isRunning())
	{
		wiicontroller->stop();
		wiicontroller->wait();
	}
	
	event->accept();
}

void MainWindow::connectController()
{
	if (wiicontroller->isRunning()) {
		connectWiimoteAct->setEnabled(false);
		wiicontroller->stop();
		wiicontroller->wait();
		connectWiimoteAct->setText(tr("Connect &Wiimote"));
		connectWiimoteAct->setEnabled(true);
		controllerUI->setInstructions(0, "");
	}
	else if (!wiiboard->isRunning()) {
		wiicontroller->start();
		connectWiimoteAct->setText(tr("Disconnect &Wiimote"));
	}
}

void MainWindow::connectBoard()
{
	if (wiiboard->isRunning()) {
		connectBoardAct->setEnabled(false);
		wiiboard->stop();
		wiiboard->wait();
		connectBoardAct->setText(tr("Connect &Balance Board"));
		connectBoardAct->setEnabled(true);
		boardUI->setInstructions(0, "");
	}
	else if (!wiicontroller->isRunning()) {
		wiiboard->start();
		connectBoardAct->setText(tr("Disconnect &Balance Board"));
	}
}

void MainWindow::reconnect()
{
	if (connector->isRunning())
	{
		connector->stop();
		connector->wait();
	}

	if (wiiboard->isRunning())
	{
		wiiboard->stop();
		wiiboard->wait();
	}

	if (wiicontroller->isRunning())
	{
		wiicontroller->stop();
		wiicontroller->wait();
	}

	std::cout << "Restarting connector" << std::endl;
	connector->start();
}

/**
 * Shows an about message box.
 */
void MainWindow::about()
{
	QMessageBox::about(this, tr("About Wii Device Driver"),
		tr("This is a proof-of-concept app that connects wii devices to Mac OS X and Windows."));
}

void MainWindow::createActions()
{
	exitAct = new QAction(tr("E&xit"), this);
	exitAct->setShortcut(tr("Ctrl+Q"));
	exitAct->setStatusTip(tr("Exit the application"));
	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

	connectWiimoteAct = new QAction(tr("Connect &Wiimote"), this);
	connectWiimoteAct->setShortcut(tr("Ctrl+W"));
	connectWiimoteAct->setStatusTip(tr("Connect the Wiimote controller"));
	connect(connectWiimoteAct, SIGNAL(triggered()), this, SLOT(connectController()));

	connectBoardAct = new QAction(tr("Connect &Balance Board"), this);
	connectBoardAct->setShortcut(tr("Ctrl+B"));
	connectBoardAct->setStatusTip(tr("Connect the Wii Balance Board"));
	connect(connectBoardAct, SIGNAL(triggered()), this, SLOT(connectBoard()));
	
	reconnectQtAct = new QAction(tr("&Reconnect"), this);
	reconnectQtAct->setShortcut(tr("Ctrl+R"));
	reconnectQtAct->setStatusTip(tr("Reconnec to the Wii devices"));
	connect(reconnectQtAct, SIGNAL(triggered()), this, SLOT(reconnect()));

	aboutAct = new QAction(tr("&About"), this);
	aboutAct->setStatusTip(tr("Show the application's About box"));
	connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));

	aboutQtAct = new QAction(tr("About &Qt"), this);
	aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
	connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void MainWindow::createMenus()
{
	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(connectBoardAct);
	fileMenu->addAction(connectWiimoteAct);
	fileMenu->addAction(reconnectQtAct);
	fileMenu->addAction(exitAct);

	helpMenu = menuBar()->addMenu(tr("&Help"));
	helpMenu->addAction(aboutAct);
	helpMenu->addAction(aboutQtAct);	
}

void MainWindow::createStatusBar()
{
	statusBar()->showMessage(tr("Ready"), 2000);
}

void MainWindow::setStatus(const QString &text, int deviceType, int)
{
	QString msg;
	
	if (deviceType == WiiDeviceDriver::TYPE_BALANCEBOARD)
		msg.append(tr("Balance Board: "));
	else if (deviceType == WiiDeviceDriver::TYPE_CONTROLLER)
		msg.append(tr("Wiimote: "));
	
	msg.append(text);
	statusBar()->showMessage(msg, 5000);
}



